package org.example.types.common;

/**
 * @author lxc18
 * @date 2025/3/14 21:14
 * @description  Redis cache key 前缀
 */
public class RedisKeysPrefix {
    public static final String flag = "_";
    //用户活动参与次数 key = user_participate_quota:userId   value = {activityId1:num,activityId2:num,}
    public static final String USER_PARTICIPATE_QUOTA = "user_participate_quota:";
    public static final String USER_PARTICIPATE_USED_QUOTA = "user_participate_used_quota:";

    public static final String USER_PARTICIPATE_IS_BLACK = "user_participate_is_black:";
    //活动信息配置 key = activity_info:activityId{activityInfo}
    // value = {activityName:xxxx,activityDesc:xxxx,startTime:xxxx,endTime:xxxx,}
    public static final String ACTIVITY_INFO = "activity_info:";

    //奖品信息配置 key = prize_info:prizeId
    // value = { prizeName:xxxx,prizeDescription:xxxx,prizeType:xxxx,probability:xxxx}
    public static final String PRIZE_INFO = "prize_info:";

    //奖品id:库存
    public static final String PRIZE_STOCK = "prize_stock:";
    //奖品id:已发放数量
    public static final String PRIZE_USED_STOCK = "prize_used_stock:";

    //库存分布式锁，奖品id+库存数量
    public static final String PRIZE_STOCK_LOCK = "prize_stock_lock:";

    //延迟队列，奖品id
    public static final String PRIZE_DELAY_QUEUE = "prize_delay_queue:";

    //活动id：策略名字：策略配置
    public static final String ACTIVITY_STRATEGY = "activity_strategy:";

    // Lua脚本，用户额度扣减，已用额度增加
    public static final String LUA_SCRIPT_QUOTA =
            "local quota = redis.call('HGET', KEYS[1], ARGV[1]) " +
                    "local used = redis.call('HGET', KEYS[2], ARGV[1]) " +
                    "if not quota or not used then return -2 end " +
                    "quota = tonumber(quota) " +
                    "used = tonumber(used) " +
                    "if quota > 0 then " +
                    "  redis.call('HINCRBY', KEYS[1], ARGV[1], -1) " +
                    "  redis.call('HINCRBY', KEYS[2], ARGV[1], 1) " +
                    "  return used + 1 " +
                    "else " +
                    "  return -1 " +
                    "end";



    // Lua 脚本,库存扣减
    public static final String LUA_SCRIPT_STOCK ="local stock_key = KEYS[1]\n" +
            "local used_stock_key = KEYS[2]\n" +
            "\n" +
            "-- 获取当前库存\n" +
            "local current_stock = tonumber(redis.call('GET', stock_key))\n" +
            "if current_stock == nil or current_stock <= 0 then\n" +
            "    return -1 -- 库存不足\n" +
            "end\n" +
            "\n" +
            "-- 扣减库存并获取新的库存\n" +
            "local new_stock = redis.call('DECR', stock_key)\n" +
            "\n" +
            "-- 增加已使用库存\n" +
            "redis.call('INCR', used_stock_key)\n" +
            "\n" +
            "-- 根据新库存判断\n" +
            "if new_stock > 0 then\n" +
            "    return 1 -- 扣减成功，剩余库存 > 0\n" +
            "elseif new_stock == 0 then\n" +
            "    return 0 -- 扣减成功，剩余库存 = 0\n" +
            "end\n";



    public static final String LUA_SCRIPT_RATE_LIMIT = "local key = KEYS[1]\n" +
            "local limit = ARGV[1]\n" +
            "local window_thr = ARGV[2]\n" +
            "\n" +
            "-- 打印入参到缓存中，方便调试\n" +
            "redis.call('SET', 'rate_limit:limit', limit)\n" +
            "redis.call('SET', 'rate_limit:window_thr', window_thr)\n" +
            "\n" +
            "-- 获取当前毫秒级时间戳\n" +
            "local now = redis.call('TIME')\n" +
            "local current_time_ms = tonumber(now[1]) * 1000 + math.floor(tonumber(now[2]) / 1000)\n" +
            "local window_start = current_time_ms - window_thr*1000  -- 3秒时间窗口\n" +
            "\n" +
            "-- 移除窗口外的旧数据 (score <= window_start)\n" +
            "redis.call('ZREMRANGEBYSCORE', key, 0, window_start)\n" +
            "\n" +
            "-- 获取当前请求总数\n" +
            "local request_count = redis.call('ZCARD', key)\n" +
            "\n" +
            "if request_count >= tonumber(limit) then\n" +
            "    return 0\n" +
            "else\n" +
            "    math.randomseed(tonumber(now[2]))\n" +
            "    local unique_id = string.format(\"%d:%d:%d\", \n" +
            "        current_time_ms, \n" +
            "        tonumber(now[2]), \n" +
            "        math.random(1000000)\n" +
            "    )\n" +
            "    redis.call('ZADD', key, current_time_ms, unique_id)\n" +
            "    redis.call('EXPIRE', key, window_thr+1)\n" +
            "    return 1\n" +
            "end\n";
    // 失败的MQ消息
    public static final String MQ_MESSAGE_FAIL = "mq_message_fail:";
}
